/**
 * RevenueSourceDAO.java
 * Created on March 21, 2007, 7:06 PM
 *
 *
 */

package edu.byu.isys413.jjenkins.data;

import java.sql.*;
import java.util.LinkedList;
import java.util.List;

/**
 * This class contains the CRUD methods for the RevenueSource Table it is also
 * extended by each sub-revenueSource. The sub RevenueSource calls the saves,
 * reads, updates delete methods in this class.
 *<p>
 * This class contains three static methods. Two of them are the getType()
 * methods. They are used to get the type of a revenue source if it is not known
 * so that the type can be passed into the revenueSource Factory.
 *
 *
 * @author      Jeff Jenkins
 * @version     1.0
 */
public abstract class RevenueSourceDAO {
    
    /**
     * This is the public save method.  It is what is called when
     * the user (controller) code wants to save or update an object
     * into the database.
     * @par RevenueSourceBO object
     * @param object the object to save
     * @throws edu.byu.isys413.jjenkins.data.DataException error handling
     */
    abstract public void save(RevenueSourceBO object) throws DataException;
    
    /**
     *  ****NOTE*** This method should contain two updates and two insert method
     *  call. One should call the superclass method  and one should call the
     *  child class method for both insert and delete.
     *
     *  This is a package method that is called by the public save (above) or
     *  by another DAO.  Either way we already have a connection to the database
     *  to use.  The user (controller) code never calls this one directly, since
     *  it can't know about Connection objects or SQLExceptions.
     *
     *  By having other DAOs call this save method (rather than update or
     *  insert below, each DAO in a chained save (like the CustomerDAO calling
     *  MembershipDAO calling InterestDAO save chain) can independently decide
     *  whether to udpate or insert the BO it's saving.  That's why I made
     *  update and insert private rather than package level -- if you call
     *  them directly from another DAO, this DAO can't decide whether it's
     *  object needs to be inserted or updated.
     * @par: RevenueSourceBO, Connection
     * @throws: SQLException, DataException
     * @param object object to save
     * @param conn connection to database
     * @throws java.sql.SQLException SQL Exception
     * @throws edu.byu.isys413.jjenkins.data.DataException Data Exception
     */
    
    
    abstract void save(RevenueSourceBO object, Connection conn) throws SQLException, DataException;
    
    /**
     * This method creates a new RevenueSourceBO with a unique QUID, puts the interest
     * in cache, and then returns it to the calling method.
     * @return returns revenue source object
     * @return: RevenueSourceBO
     * @throws edu.byu.isys413.jjenkins.data.DataException Data Exception
     * @throws: DataException
     */
    abstract public RevenueSourceBO create() throws DataException;
    
    /**
     * This is the public read statement.  It loads an existing record
     * from the database.
     * @param id id of revenue source
     * @return returns object
     * @Par: String: id
     * @Return: RevenueSourceBO
     * @Throws: DataException
     * @throws edu.byu.isys413.jjenkins.data.DataException data exception
     */
    abstract public RevenueSourceBO read(String id) throws DataException;
    
    
    /**
     *  This is a package method that is called by the public read (above) or
     *  by another DAO.  Either way we already have a connection to the database
     *  to use.  The user (controller) code never calls this one directly, since
     *  it can't know about Connection objects or SQLExceptions.
     * @param id id of revenue source
     * @param conn connection to database
     * @return object
     * @Par: String: id, Connection conn
     * @Return: RevenueSouceBO
     * @throws java.sql.SQLException SQL Exception
     * @throws edu.byu.isys413.jjenkins.data.DataException Data Exception
     * @throws: DataException, SQLException
     */
    abstract RevenueSourceBO read(String id, Connection conn) throws SQLException, DataException;
    
    
    /**
     * This method is static and allows the user to find the revenue source type
     * based on an id. This type is then passed into the RevenueSource factory
     * to find the correct DAO.
     * @param id id of revenue source
     * @return String type of revenuesource
     * @throws DataException Data Exception
     */
    
    public static synchronized String getType(String id) throws DataException {
        
        String type;
        Cache c = Cache.getInstance();
//        if(c.containsKey(id)){
//            SaleBO thing = (SaleBO) c.get(id);
//            type = thing.getType();
//        }else{
            
            try {
                
                // Gets connection
                ConnectionPool connPool = ConnectionPool.getInstance();
                Connection conn = connPool.get();
                
                try {
                    //reads in object
                    type = getType(id, conn);
                    
                }catch (SQLException e) {
                    conn.rollback();
                    throw new DataException("Could not retrieve type for id=" + id, e);
                    
                }
                
                // connection committs and is returned.
                conn.commit();
                connPool.release(conn);
                
                
                
            } catch (SQLException e) {
                throw new DataException("Could not retrieve record for id=" + id, e);
            } catch (DataException e) {
                throw new DataException("Could not retrieve record for id=" + id, e);
            } catch (ConnectionPoolException e) {
                throw new DataException("Could not retrieve record for id=" + id, e);
            }
            
            // Return object
//        }//else
        return type;
    }
    
    /**
     *  This is a package method that is called by the public read (above) or
     *  by another DAO.  Either way we already have a connection to the database
     *  to use.  The user (controller) code never calls this one directly, since
     *  it can't know about Connection objects or SQLExceptions.
     * @param id id of revenue source
     * @param conn connection to database
     * @return String type type of revenuesource
     * @throws java.sql.SQLException SQL Exception
     * @throws edu.byu.isys413.jjenkins.data.DataException Data Exception
     */
    synchronized static String getType(String id, Connection conn) throws SQLException, DataException {
        
        String type = null;
        RevenueSourceBO object = new ServiceRepairBO();
        
        // Quieries that database
        
        PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM revenue_source WHERE revenue_source_id = ?");
        pstmt.setString(1, id);
        pstmt.execute();
        ResultSet rs= pstmt.getResultSet();
        
                if (rs.next()) {
                type = rs.getString("rev_type");
        }

        
        // returns object
        return type;
    }
    
    
    /**
     * This method recieves a revenueSource Object and populates it the data
     * contained in the revenueSource table
     *
     * @param RevenueSourceBO object
     */
    protected synchronized RevenueSourceBO populateRevenueSource(RevenueSourceBO object, Connection conn) throws SQLException, DataException {
        
        PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM revenue_source WHERE revenue_source_id = ?");
        pstmt.setString(1, object.getId());
        pstmt.execute();
        ResultSet rs = pstmt.getResultSet();
        
        if (rs.next()) {
            object.setType(rs.getString("rev_type"));
            object.setDescription(rs.getString("description"));
            object.setPrice(rs.getDouble("price"));
            object.setQuantity(rs.getDouble("quantity"));
        }
        
        
        // returns object
        return object;
    }
    
    
    /**
     * These methods are called from the save method in the sub-revenue class.
     * They save the id and type to the revenue source table
     * @param object revneue source object
     * @param conn connection to database
     * @paramRevenueSourceBO object
     * @throws java.sql.SQLException SQL Exception
     * @throws edu.byu.isys413.jjenkins.data.DataException DataException
     */
    protected synchronized void update(RevenueSourceBO object, Connection conn) throws SQLException, DataException {
        
        PreparedStatement pstmt = conn.prepareStatement("UPDATE revenue_source SET revenue_source_id = ?, rev_type = ?, price = ?, description = ?, quantity = ? WHERE revenue_source_id = ?");
        pstmt.setString(1, object.getId());
        pstmt.setString(2, object.getType());
        pstmt.setDouble(3, object.getPrice());
        pstmt.setString(4, object.getDescription());
        pstmt.setDouble(5, object.getQuantity());
        pstmt.setString(6, object.getId());
        
        pstmt.execute();
        
    }
    
    /**
     * These methods are called from the save method in the sub-revenue class.
     * They save the id and type to the revenue source table
     * @param object revenue source object
     * @param conn connection to database
     * @paramRevenueSourceBO object
     * @throws java.sql.SQLException SQL Exception
     * @throws edu.byu.isys413.jjenkins.data.DataException Data Exception
     */
    protected synchronized void insert(RevenueSourceBO object, Connection conn) throws SQLException, DataException {
        
        // Creates prepared statemetn
        PreparedStatement pstmt = conn.prepareStatement("INSERT INTO revenue_source VALUES(?, ?, ?, ?, ?)");
        pstmt.setString(1, object.getId());
        System.out.println(object.getType());
        pstmt.setString(2, object.getType());
        System.out.println(object.getPrice());
        pstmt.setDouble(3, object.getPrice());
        pstmt.setString(4, object.getDescription());
        pstmt.setDouble(5, object.getQuantity());
        
        //Executes prepated statement
        pstmt.execute();
        
        //Sets already in database true is done in the subclass
        
    }
    
    
    /**
     * This method deletes an object from the database
     * @param objects revenue source object
     * @throws edu.byu.isys413.jjenkins.data.DataException data exception
     */
    
    public synchronized void delete(RevenueSourceBO objects)throws DataException{
        // You are not allowed to delete something from the RevenueSource Table at this time
        
        throw new DataException("You can not delete a RevenueSourceBO at this time");
        
    }
    
    /** Creates a new instance of RevenueSourceDAO */
    public RevenueSourceDAO() {
    }
    
}

